#pragma once
#include <iostream>
#include <vector>
#include <queue>
#include <pthread.h>
#include "Task.hpp"
#include "pthread.hpp"
#include "lock_guard.hpp"

using namespace pthread_moudle;

template <typename T>
class threadpool
{
private:
    void LockQueue()
    {
        pthread_mutex_lock(&_mutex);
    }
    void UnLockQueue()
    {
        pthread_mutex_unlock(&_mutex);
    }
    void ThreadSleep()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }
    void WakeUpThread()
    {
        //std::cout<<"wakeup"<<std::endl;
        pthread_cond_broadcast(&_cond);
    }
    void WakeUpAllThread()
    {
        pthread_cond_broadcast(&_cond);
    }
    // 线程处理任务函数，注意：这里会传入this，需要进行处理
    void Handlertask(std::string name)
    {
        while (true)
        {
            LockQueue();
            // 当队列为空且线程池正在运行
            while (_task_queue.empty() && _is_running)
            {
                _waitnum++;    // 等待的线程++
                ThreadSleep(); // 进入等待
                _waitnum--;    // 被唤醒即--
            }
            // 当队列为空且线程池已经停止运行
            if (_task_queue.empty() && !_is_running)
            {
                //std::cout << name << "exit" << std::endl;
                UnLockQueue();
                break; // 退出
            }

            // 当队列不为空,无论is_running的状态如何，都要先将队列内任务全部执行
            //  从队列中拿取任务并执行
            T t;
            t = _task_queue.front();
            _task_queue.pop();
            std::cout << name<<"  ";
            t.Debug();
            std::cout<< t() << "   queue.size=" << _task_queue.size() << std::endl;
            //std::cout<<"thread excute counts: "<<cnt<<std::endl;
            UnLockQueue();
        }
    }

public:
    // 以下是可以提供给主线程的成员函数
    threadpool(int threadnum)
        : _threadnum(threadnum),
          _is_running(true)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
    }

    // 禁用拷贝与赋值重载
    threadpool(const threadpool &tp) = delete;
    threadpool &operator=(const threadpool &tp) = delete;
    void InitThreads()
    {
        for (int i = 0; i < _threadnum; i++)
        {
            std::string name = "thread--" + std::to_string(i + 1);
            _Threads.emplace_back(std::bind(&threadpool::Handlertask, this, std::placeholders::_1), name);
        }
    }
    void StartAll()
    {
        for (auto &thread : _Threads)
            thread.start();
    }

    // 主线程向任务队列插入任务
    void enqueue(T in)
    {
        LockQueue();
        if (_is_running)
        {
            _task_queue.push(in);
            if (_waitnum > 0)
            {
                //std::cout<<"waiting threads"<<_waitnum<<std::endl;
                WakeUpThread();
            }      
        }
        UnLockQueue();
    }
    void WaitAll()
    {
        for (auto &thread : _Threads)
            thread.join();
    }
    void Stop()
    {
        LockQueue();
        _is_running = false;
        WakeUpAllThread();
        UnLockQueue();
    }
    ~threadpool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }

private:
    int _threadnum;               // 线程池内线程的数量
    std::queue<T> _task_queue;    // 任务队列，不限大小
    std::vector<Thread> _Threads; // 线程数组

    pthread_mutex_t _mutex; // 保护任务队列的锁
    pthread_cond_t _cond;   // 保护任务队列的条件变量

    bool _is_running; // 线程池运行状态
    int _waitnum;     // 线程池内当前正在等待的线程个数
};